import or1200_definitions
import sys
sys.path.append("..")
import pyrtl
from  pyrtl import GPUSim

class Or1200Cfgr(object):
    def __init__(self):
        self.spr_addr = pyrtl.Input(bitwidth=32, name='cfgr_spr_addr')
        # self.spr_dat_o = pyrtl.Output(bitwidth=32)
        self.spr_dat_o = pyrtl.Output(bitwidth=32,name='spr_dat_o')

        implvr = ImplVr()
        implvr.spr_addr <<= self.spr_addr
        self.spr_dat_o <<= implvr.spr_dat_o

class Or1200Cfgr_wire(object):
    def __init__(self):
        self.spr_addr = pyrtl.WireVector(bitwidth=32)
        # self.spr_dat_o = pyrtl.WireVector(bitwidth=32)
        self.spr_dat_o = pyrtl.WireVector(bitwidth=32)

        implvr = ImplVr()
        implvr.spr_addr <<= self.spr_addr
        self.spr_dat_o <<= implvr.spr_dat_o

class ImplVr(object):
    def __init__(self):
        self.spr_addr = pyrtl.WireVector(bitwidth=32)
        self.spr_dat_o = pyrtl.WireVector(bitwidth=32)
        
        spr_dat_o = [i for i in self.spr_dat_o]
        with pyrtl.conditional_assignment:
            with or1200_definitions.Or_Not(self.spr_addr[4:32]):
                with self.spr_addr[0:4] == or1200_definitions.OR1200_SPRGRP_SYS_VR:
                    spr_dat_o[or1200_definitions.OR1200_VR_REV_BITS] = or1200_definitions.OR1200_VR_REV
                    spr_dat_o[or1200_definitions.OR1200_VR_RES1_BITS] = or1200_definitions.OR1200_VR_RES1
                    spr_dat_o[or1200_definitions.OR1200_VR_CFG_BITS] = or1200_definitions.OR1200_VR_CFG
                    spr_dat_o[or1200_definitions.OR1200_VR_VER_BITS] = or1200_definitions.OR1200_VR_VER
                    self.spr_dat_o |= pyrtl.concat(*reversed(spr_dat_o))
                with self.spr_addr[0:4] == or1200_definitions.OR1200_SPRGRP_SYS_UPR:
                    spr_dat_o[or1200_definitions.OR1200_UPR_UP_BITS] = or1200_definitions.OR1200_UPR_UP
                    spr_dat_o[or1200_definitions.OR1200_UPR_DCP_BITS] = pyrtl.Const(0b0, bitwidth=1)
                    spr_dat_o[or1200_definitions.OR1200_UPR_ICP_BITS] = pyrtl.Const(0b0, bitwidth=1)
                    spr_dat_o[or1200_definitions.OR1200_UPR_DMP_BITS] = pyrtl.Const(0b0, bitwidth=1)
                    spr_dat_o[or1200_definitions.OR1200_UPR_IMP_BITS] = pyrtl.Const(0b0, bitwidth=1)
                    spr_dat_o[or1200_definitions.OR1200_UPR_MP_BITS] = or1200_definitions.OR1200_UPR_MP
                    spr_dat_o[or1200_definitions.OR1200_UPR_DUP_BITS] = or1200_definitions.OR1200_UPR_DUP
                    spr_dat_o[or1200_definitions.OR1200_UPR_PCUP_BITS] = or1200_definitions.OR1200_UPR_PCUP
                    spr_dat_o[or1200_definitions.OR1200_UPR_PMP_BITS] = or1200_definitions.OR1200_UPR_PMP
                    spr_dat_o[or1200_definitions.OR1200_UPR_PICP_BITS] = or1200_definitions.OR1200_UPR_PICP
                    spr_dat_o[or1200_definitions.OR1200_UPR_TTP_BITS] = or1200_definitions.OR1200_UPR_TTP
                    spr_dat_o[or1200_definitions.OR1200_UPR_RES1_BITS] = or1200_definitions.OR1200_UPR_RES1
                    spr_dat_o[or1200_definitions.OR1200_UPR_CUP_BITS] = or1200_definitions.OR1200_UPR_CUP
                    self.spr_dat_o |= pyrtl.concat(*reversed(spr_dat_o))
                with self.spr_addr[0:4] == or1200_definitions.OR1200_SPRGRP_SYS_CPUCFGR:
                    spr_dat_o[or1200_definitions.OR1200_CPUCFGR_NSGF_BITS] = or1200_definitions.OR1200_CPUCFGR_NSGF
                    spr_dat_o[or1200_definitions.OR1200_CPUCFGR_HGF_BITS] = or1200_definitions.OR1200_CPUCFGR_HGF
                    spr_dat_o[or1200_definitions.OR1200_CPUCFGR_OB32S_BITS] = or1200_definitions.OR1200_CPUCFGR_OB32S
                    spr_dat_o[or1200_definitions.OR1200_CPUCFGR_OB64S_BITS] = or1200_definitions.OR1200_CPUCFGR_OB64S
                    spr_dat_o[or1200_definitions.OR1200_CPUCFGR_OF32S_BITS] = or1200_definitions.OR1200_CPUCFGR_OF32S
                    spr_dat_o[or1200_definitions.OR1200_CPUCFGR_OF64S_BITS] = or1200_definitions.OR1200_CPUCFGR_OF64S
                    spr_dat_o[or1200_definitions.OR1200_CPUCFGR_OV64S_BITS] = or1200_definitions.OR1200_CPUCFGR_OV64S
                    spr_dat_o[or1200_definitions.OR1200_CPUCFGR_RES1_BITS] = or1200_definitions.OR1200_CPUCFGR_RES1
                    self.spr_dat_o |= pyrtl.concat(*reversed(spr_dat_o))
                with self.spr_addr[0:4] == or1200_definitions.OR1200_SPRGRP_SYS_DCFGR:
                    spr_dat_o[or1200_definitions.OR1200_DCFGR_NDP_BITS] = or1200_definitions.OR1200_DCFGR_NDP
                    spr_dat_o[or1200_definitions.OR1200_DCFGR_WPCI_BITS] = or1200_definitions.OR1200_DCFGR_WPCI
                    spr_dat_o[or1200_definitions.OR1200_DCFGR_RES1_BITS] = or1200_definitions.OR1200_DCFGR_RES1
                    self.spr_dat_o |= pyrtl.concat(*reversed(spr_dat_o))
                with pyrtl.otherwise:
                    self.spr_dat_o |= pyrtl.Const(0x0, bitwidth=32)
            with pyrtl.otherwise:
                self.spr_dat_o |= pyrtl.Const(0x0, bitwidth=32)
                
if __name__ == '__main__':
    cfgr = Or1200Cfgr()
    sim = pyrtl.GPUSim_now.GPUSim('cfgr')

    com = pyrtl.CompiledSimulation()

    input_width = []
    from pyrtl.wire import Input

    IN = pyrtl.working_block().wirevector_subset(Input)
    for inn in IN:
        name = inn.name
        width = inn.bitwidth
        input_width.append([name, width])
    import random

    max_ = 0
    com_time = 0
    ess_time = 0
    num = 1
    for i in range(num):
        print(i)

        inputs_random = {}
        inputs_select = {}
        inputs_old = {}
        inputs_ = {}

        for inp in input_width:
            inputs_random[inp[0]] = []
            inputs_select[inp[0]] = []
            result = random.randint(0, 2 ** inp[1] - 1)
            inputs_old[inp[0]] = result

        for j in range(131072):
            for inp in input_width:
                result = random.randint(0, 2 ** inp[1] - 1)
                inputs_[inp[0]] = result
                inputs_random[inp[0]].append(result)
            if random.random() < 0.2:
                for name in inputs_old:
                    inputs_select[name].append(inputs_old[name])
            else:
                for name in inputs_:
                    inputs_select[name].append(inputs_[name])
                    inputs_old[name] = inputs_[name]
        time1 = com.step_multiple(inputs_select)

    sim.make_input(inputs_select)


